Release 10.1A: OpenEdge Application Server:
Developing WebSpeed Applications
Complex HTML mapping
Figure 2–6 shows an example of an HTML-mapping Web object that is more typical of those that you might find in a full-featured Web application. The Web object, generated from the example code in
w-cstinf.w, maps to an HTML form with submit buttons and returns customer information from the Sports2000 database.Figure 2–6: Web page generated from w-cstinf.w
![]()
Basically, the Web object does the following:
- Initially, it generates a Web page similar to Figure 2–6. The Web page contains several buttons and form fields that contain information from the first record (according to the value of
CustNum) of the Customer table of the Sports2000 database.- If you enter a value in the Enter Name field and choose the Search button, the Web object takes the value and finds the customer whose name is equal to or greater than the entered value.
Thus, entering the value
Darcausesw-cstinf.wto return the first customer whose name begins withDar(which is Dark Alley Bowling).- The Next button finds and returns the customer record that comes just after the record specified by the current value of the
Nameelement.- If you change any of the displayed fields, the Update button causes the Web object to update the appropriate customer record.
After successfully updating the database, the Web object returns the updated Web page with a comment containing today’s date appended to the current
Commentvalue. This appended value is also stored in the database for future reference.The following shows
w-custinf.htm, which is the HTML file mapped tow-cstinf.w:
The Web object makes explicit reference to two form elements in this file:
You can follow how the Web object runs by looking at the relevant code sections of the
process-web-requestprocedure forw-cstinf.w.When the user first goes to the URL for this Web object,
w-cstinf.wreturns the form defined inw-cstinf.htmto the browser. It does this by executing theprocess-web-requestprocedure. First, the procedure generates the default HTTP header for the Web page that the object is about to return, by calling the defaultoutputHeaderprocedure (STEP0in the code):
It then determines whether the CGI request method is a
GETor aPOST. In this case, as the first URL request, it is aGET, causing the code to take theELSEbranch of the test:
The default procedures in this code branch move any initial data to the form buffer, set up the input form elements to receive user input, and send out the prepared Web page.
Note: None of this initialGETrequest requires you to add any additional code toprocess-web-request. However, you might want to improve the way the Web object fetches the first record. By default, it finds the first record according to the value ofCustNum. It might be more useful to display the first customer alphabetically by Name. To change the default behavior, comment outRun findRecords. Then, add a line of SpeedScript (for example,FINDFIRSTcustomerUSE-INDEXname.)The Web object returns a page to the browser that looks similar to Figure 2–6. The Web page is interactive. The user can view a different record by using the Submit or Next buttons. In addition, the user can change a record by using the Update button. In order to implement this functionality, the following highlighted code is added to the
POSTbranch ofprocess-web-request(recall thatPOSTis specified as the request method inw-custinf.htm):
The first code fragment calls the
get-valueAPI function to return a value when the submit button is selected:
This function returns the value of any form element or CGI query string element when given the element name. In
w-cstinf.htm,"Button Value"is the name of allSUBMITbuttons defined in the form (with values"Search","Next", and"Update"). So, the value of the button that the user pressed to initiate thisPOSTis returned in the variablevButton.The
vButtonvariable is defined in the definitions section that is global to all procedures in the Web object,w-cstinf.w. (Look in the Definitions section of the Section Editor.) This variable has the data typeCHARACTER, a variable-length string data type:
Note: The
NO-UNDOoption is often used to improve SpeedScript memory efficiency. It prevents the automatic saving-to-disk of the specified variable for recovery from a failed database transaction. For more information on database transactions, see Chapter 8, " Controlling Database Transactions."The form input values sent with the URL is read by calling the default
inputFieldsprocedure (STEP1).Next, the Customer record based on the value of the
SUBMITbutton is located. This is done by executing thefindCustomerprocedure (STEP2in thePOSTbranch).In the code for
findCustomer, you can see that a newly defined character variable,vName, receives the value of the Name form element entered by the user.The scope of this variable is local to the
findCustomerprocedure. However, access to thevButtonvariable still exists, since it is declared in a section whose scope is the entire Web object:
The code first returns the value of the
Nameform element from theget-valueAPI function. Then it checks for the three possible values of the Submit button returned inprocess-web-request. This is done using aCASEstatement. It executes theWHENoption that specifies the current value of theCASEstatement expression, in this case,vButton.In the case of
Note: The“Search", the first customer record whoseNamefield is equal to or greater than the value of the Name form element is found. If such a record does not exist, it returns the first customer record to restart the search. If no customers are on file, it returns a suitable message in the Name form element.WITHFRAME{&FRAME-NAME}option indicates that all data item references in the block (in this case aDOblock) that require a parent SpeedScript frame default to{&FRAME-NAME}. This is a shortcut to avoid specifying a frame for each data item reference.In the case of
Note: The current value of Name is being used as if it were the name that the user last requested. However, there is no guarantee of this, since the user could change the value before submitting the form. If this Web object were state aware, you could replace the“Next", the processing is almost the same as for“Search". Assuming that the user has already seen this record, it searches for the record with the next greater value forName. Again, if no such record exists, it returns the first record, and if no customers are on file it returns a suitable message.FINDFIRSTCustomerstatement with aFINDNEXTCustomerstatement that would automatically find the next Customer record after the current one in the database. This guarantees that the application returns the next record found and not the one based on the returned value of the Name form element. In a stateless Web object, there is no previous record, since it always executes as if for the first time. Thus, the entered value ofNamemust be used. (You could also use a hidden HTML form element to duplicate the returned value of the databaseNamefield for later reference.) The Web object examples do include a state-aware version of this Web object,w-cststa.w, which you can compare tow-cstinf.w. For more information on building state-aware Web objects, see Chapter 7, " Controlling WebSpeed Transactions."For
“Update", you must find a unique record that corresponds to the returned values, because there can be duplicate customer names. Since theCustNumfield is the primary key for Customer records, you can assume that the value passed back in theCustNumform element specifies the record intended for update. However, the user could have changed it. If there is no such record, or the specified record is locked by another client, the form element Name value is replaced with a suitable message.If the record does exist, a confirmation is concatenated (
Note: The+) to the Comments form element value, both for immediate confirmation and for future reference. The SpeedScriptTODAYfunction returns today’s date, and theSTRINGfunction converts theDATEvalue (a separate data type) to a character string for the concatenation. Also,~nspecifies a new line in a string.FINDstatement for the“Update"case specifies that the retrieved record be locked (EXCLUSIVE-LOCK). This prevents other clients from updating the record while the current update takes place. For more information on record locking in SpeedScript, see the OpenEdge Development: Progress 4GL Reference .At this point, the
process-web-requestmethod procedure has either found the record or has not found the record that the user intended to update. The procedure returns fromfindCustomerand executes the following code fromw-cstinf.w (POST branch):
The test of
vButtonis added, again, because the next default event procedure,assignFields, assumes that you want to update the current record with the values received from the user. However, this is only true if the user submitted the form for update, and only if the specified record was actually found. The SpeedScriptAVAILABLEfunction returns a logical value ofTRUEif there is a record in the buffer for the specified database table, in this case,Customer.The remaining default event procedures in the
POSTrequest branch move the field values from the current (possibly updated) record to the form buffer, prepare any form elements for further input from the user, and output the Web page with the resulting content to the browser.
|
Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095 |